package org.yx.service.smat.save_receive_material_and_print;

import com.xiaoleilu.hutool.date.DateUtil;
import com.xiaoleilu.hutool.util.NumberUtil;
import com.xiaoleilu.hutool.util.StrUtil;
import org.dbist.dml.Query;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.yx.exception.BizException;
import org.yx.models.SbasMatDef;
import org.yx.models.SmatMsnSts;
import org.yx.models.SmatRcvLbl;
import org.yx.service.bas.create_rule_code.BasCreateRuleCodeService;
import org.yx.service.smat.insert_material_sn_history.SmatInsertMaterialSnHistoryIn;
import org.yx.service.smat.insert_material_sn_history.SmatInsertMaterialSnHistoryService;
import org.yx.service.smat.view_material_sn_to_print_label.SmatViewMaterialSnToPrintLabelIn;
import org.yx.service.smat.view_material_sn_to_print_label.SmatViewMaterialSnToPrintLabelService;
import org.yx.utils.BaseService;
import org.yx.utils.Const;
import org.yx.utils.FieldMap;
import org.yx.utils.ServiceBeanUtil;
import yxmes.tools.FineReportUtil;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 保存收货记录并打印
 *
 * @author zxw
 * @since 2023/03/13
 **/
public class SmatSaveReceiveMaterialAndPrintService extends BaseService {
    private final static String MSN_CODE = "MSN";

    @Transactional(propagation = Propagation.NOT_SUPPORTED,readOnly = true)
    public SmatSaveReceiveMaterialAndPrintOut saveReceiveMaterialAndPrint(SmatSaveReceiveMaterialAndPrintIn in) throws Exception {
        List<String> msns = ServiceBeanUtil.getBean(SmatSaveReceiveMaterialAndPrintService.class).saveData(in);

        SmatSaveReceiveMaterialAndPrintOut out = new SmatSaveReceiveMaterialAndPrintOut();
        SmatViewMaterialSnToPrintLabelIn printLabelIn = new SmatViewMaterialSnToPrintLabelIn();
        printLabelIn.setMsns(StrUtil.join(",", msns.toArray()));

        out.setFileName(ServiceBeanUtil.getBean(SmatViewMaterialSnToPrintLabelService.class).viewMaterialSnToPrintLabel(printLabelIn).getFileName());


        return out;
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Throwable.class)
    public List<String> saveData(SmatSaveReceiveMaterialAndPrintIn in) throws Exception {
        checkStringNotBlank(in, "supCode,matCode");
        if (in.getDeliveryQty().compareTo(BigDecimal.ZERO) <= 0) {
            throw new BizException("SYS-0004", FieldMap.of("parameter", "deliveryQty"));
        }
        if (in.getLabelQty().compareTo(BigDecimal.ZERO) <= 0) {
            throw new BizException("SYS-0004", FieldMap.of("parameter", "labelQty"));
        }

        Query queryMat = new Query();
        queryMat.addFilter("orgCode", in.getUserOrgCode());
        queryMat.addFilter("matCode", in.getMatCode());
        queryMat.addFilter("matStatus", "N");
        SbasMatDef matDef = selectOne(SbasMatDef.class, queryMat);
        if (matDef == null) {
            throw new BizException("SBAS-0002", "物料${matCode}不存在或已经删除。", FieldMap.of("matCode", in.getMatCode()));
        }

        //送货数/每个标签数得到最大满足的标签数
        int lessPrintCnt = (int) Math.floor(in.getDeliveryQty().divide(in.getLabelQty(), RoundingMode.FLOOR).doubleValue());
        //还可能有余
        BigDecimal remainQty = in.getDeliveryQty().subtract(new BigDecimal(lessPrintCnt).multiply(in.getLabelQty()));

        List<SmatRcvLbl> lblList = new ArrayList<SmatRcvLbl>();
        List<SmatMsnSts> msnStsList = new ArrayList<SmatMsnSts>();
        List<String> msns = new ArrayList<String>();
        while (lessPrintCnt-- > 0) {
            SmatRcvLbl lbl = new SmatRcvLbl();
            lbl.setOrgCode(in.getUserOrgCode());
            lbl.setMsn(BasCreateRuleCodeService.createRuleCode(MSN_CODE));
            lbl.setPoNo(in.getPoNo());
            lbl.setSupCode(in.getSupCode());
            lbl.setDeliveryNo(in.getDeliveryNo());
            lbl.setDeliveryQty(in.getDeliveryQty());
            lbl.setMatCode(in.getMatCode());
            lbl.setProdDate(in.getProdDate());
            lbl.setProdLot(in.getProdLot());
            lbl.setWhCode(in.getWhCode());
            lbl.setQty(in.getLabelQty());
            lbl.setUnit(StrUtil.nullToDefault(in.getUnit(), matDef.getMatUnit()));
            lbl.setPrintCnt(1);
            lbl.setPrintUser(in.getUserToken().getUserId());
            lbl.setStatus("N");
            lbl.setInInvQty(in.getLabelQty());
            lbl.setOutInvQty(BigDecimal.ZERO);

            lblList.add(lbl);

            SmatMsnSts msnSts = new SmatMsnSts();
            msnSts.setOrgCode(lbl.getOrgCode());
            msnSts.setMsn(lbl.getMsn());
            msnSts.setMatCode(lbl.getMatCode());
            msnSts.setMatVer(matDef.getMatVer());
            msnSts.setQty(lbl.getQty());
            msnSts.setUnit(lbl.getUnit());
            msnSts.setWhCode(lbl.getWhCode());
            msnSts.setMsnType("M");
            msnSts.setDtlSeq(1);
            msnSts.setStatus("I");
            msnSts.setEventCode("RECEIVE");
            msnSts.setEventValue(lbl.getDeliveryNo());
            msnSts.setSupCode(lbl.getSupCode());
            msnSts.setSupProdDate(lbl.getProdDate() == null ? null : DateUtil.format(lbl.getProdDate(), Const.DATE_LONG_FORMAT));
            msnSts.setSupProdLot(lbl.getProdLot());
            msnStsList.add(msnSts);

            msns.add(msnSts.getMsn());
        }

        if (remainQty.compareTo(BigDecimal.ZERO) > 0) {
            SmatRcvLbl lbl = new SmatRcvLbl();
            lbl.setOrgCode(in.getUserOrgCode());
            lbl.setMsn(BasCreateRuleCodeService.createRuleCode(MSN_CODE));
            lbl.setPoNo(in.getPoNo());
            lbl.setSupCode(in.getSupCode());
            lbl.setWhCode(in.getWhCode());
            lbl.setDeliveryNo(in.getDeliveryNo());
            lbl.setDeliveryQty(in.getDeliveryQty());
            lbl.setMatCode(in.getMatCode());
            lbl.setProdDate(in.getProdDate());
            lbl.setProdLot(in.getProdLot());
            lbl.setQty(remainQty);
            lbl.setUnit(StrUtil.nullToDefault(in.getUnit(), matDef.getMatUnit()));
            lbl.setPrintCnt(1);
            lbl.setPrintUser(in.getUserToken().getUserId());
            lbl.setStatus("N");
            lbl.setInInvQty(remainQty);
            lbl.setOutInvQty(BigDecimal.ZERO);

            lblList.add(lbl);

            SmatMsnSts msnSts = new SmatMsnSts();
            msnSts.setOrgCode(lbl.getOrgCode());
            msnSts.setMsn(lbl.getMsn());
            msnSts.setMatCode(lbl.getMatCode());
            msnSts.setMatVer(matDef.getMatVer());
            msnSts.setWhCode(lbl.getWhCode());
            msnSts.setQty(lbl.getQty());
            msnSts.setUnit(lbl.getUnit());
            msnSts.setMsnType("M");
            msnSts.setDtlSeq(1);
            msnSts.setStatus("N");
            msnSts.setEventCode("RECEIVE");
            msnSts.setEventValue(lbl.getDeliveryNo());
            msnSts.setSupCode(lbl.getSupCode());
            msnSts.setSupProdDate(lbl.getProdDate() == null ? null : DateUtil.format(lbl.getProdDate(), Const.DATE_LONG_FORMAT));
            msnSts.setSupProdLot(lbl.getProdLot());
            msnStsList.add(msnSts);

            msns.add(msnSts.getMsn());
        }

        insertBatch(lblList);
        insertBatch(msnStsList);
        SmatInsertMaterialSnHistoryIn msnHisIn = new SmatInsertMaterialSnHistoryIn();
        msnHisIn.setMsnStsList(msnStsList);
        ServiceBeanUtil.getBean(SmatInsertMaterialSnHistoryService.class).insertMaterialSnHistory(msnHisIn);

        return msns;
    }
}